package protocol.JT808_2019;

import javax.print.DocFlavor;
import java.util.HashMap;

public class Handle808_2019JT01 implements IHandle808_2019JT {

    @Override
    public String handle(JT808_2019Cmd cmd) {
        byte subOrder = cmd.subOrder();

        switch (subOrder){
            case 0x00:
                return handle0100(cmd);
            case 0x02:
                return handle0102(cmd);
            case 0x04:
                return handle0104(cmd);
            case 0x07:
                return handle0107(cmd);
            case 0x08:
                return handle0108(cmd);
            default:
                return "808-2019:未匹配的命令字"+(cmd.readOrder()+","+cmd.subOrder());
        }
    }

    private String handle0100(JT808_2019Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("终端->平台:终端注册");
        builder.append("\r\n");
        builder.append("省域ID："+cmd.readInt(2));
        builder.append("\r\n");
        builder.append("市县域："+cmd.readInt(2));
        builder.append("\r\n");

        builder.append("制造商ID："+cmd.readBCD(11));
        builder.append("\r\n");
        builder.append("终端型号："+cmd.readBCD(30));
        builder.append("\r\n");
        builder.append("终端ID："+cmd.readBCD(30));
        builder.append("\r\n");
        builder.append("车牌颜色："+cmd.readBCD(1));
        builder.append("\r\n");
        builder.append("车牌："+cmd.readString(-1));
        builder.append("\r\n");


        return builder.toString();
    }

    private String handle0108(JT808_2019Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("终端->平台:升级结果应答");
        builder.append("\r\n");
        int type = cmd.readInt(1);
        HashMap<Integer,String> list = new HashMap<>();
        list.put(0,"终端");
        list.put(12,"道路运输证IC读卡器");
        list.put(52,"卫星定位模块");
        builder.append("升级类型("+type+"):"+list.getOrDefault(type,"未定义"));
        builder.append("\r\n");

        type = cmd.readInt(1);
        list.clear();
        list.put(0,"成功");
        list.put(1,"失败");
        list.put(2,"取消");
        builder.append("升级结果("+type+"):"+list.getOrDefault(type,"未定义"));
        builder.append("\r\n");

        return builder.toString();
    }

    private String handle0107(JT808_2019Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("终端->平台:查询终端属性应答");
        builder.append("\r\n");
        int value = cmd.readWORD();
        builder.append("终端类型:"+value);
        builder.append("\r\n");
        builder.append("    是否适用客运车辆（1为适用）:"+(value&0x01));
        builder.append("\r\n");
        builder.append("    是否适用危险品车辆（1为适用）:"+(value>>1&0x01));
        builder.append("\r\n");
        builder.append("    是否适用普通货运车辆（1为适用）:"+(value>>2&0x01));
        builder.append("\r\n");
        builder.append("    是否适用出租车辆（1为适用）:"+(value>>3&0x01));
        builder.append("\r\n");
        builder.append("    是否支持硬盘录像车辆（1为支持）:"+(value>>6&0x01));
        builder.append("\r\n");
        builder.append("    是否为一体机（1则是）:"+(value>>7&0x01));
        builder.append("\r\n");
        builder.append("    是否适用挂车（1为适用）:"+(value>>8&0x01));
        builder.append("\r\n");
        builder.append("制造商ID:"+cmd.readBCD(5));
        builder.append("\r\n");
        builder.append("终端型号:"+cmd.readBCD(30));
        builder.append("\r\n");
        builder.append("终端ID:"+cmd.readBCD(30));
        builder.append("\r\n");
        builder.append("终端SIM卡ICCID:"+cmd.readBCD(10));
        builder.append("\r\n");
        builder.append("硬件版本号:"+cmd.readString(cmd.readInt(1)));
        builder.append("\r\n");

        builder.append("固件版本号:"+cmd.readString(cmd.readInt(1)));
        builder.append("\r\n");

        builder.append("GNSS定位模式:");
        value = cmd.readInt(1);
        builder.append("    GPS定位（0:禁用,1:启用）:"+(value&0x01));
        builder.append("\r\n");
        builder.append("    北斗定位（0:禁用,1:启用）:"+(value>>1&0x01));
        builder.append("\r\n");
        builder.append("    GLONASS（0:禁用,1:启用）:"+(value>>2&0x01));
        builder.append("\r\n");
        builder.append("    Galileo（0:禁用,1:启用）:"+(value>>3&0x01));

        builder.append("通讯模块属性:");
        value = cmd.readInt(1);
        builder.append("    GPRS通信（1:支持）:"+(value&0x01));
        builder.append("\r\n");
        builder.append("    CDMA通信（1:支持）:"+(value>>1&0x01));
        builder.append("\r\n");
        builder.append("    TD-SCDMA通信（1:支持）:"+(value>>2&0x01));
        builder.append("\r\n");
        builder.append("    WCDMA通信（1:支持）:"+(value>>3&0x01));
        builder.append("\r\n");
        builder.append("    SCDMA2000通信（1:支持）:"+(value>>4&0x01));
        builder.append("\r\n");
        builder.append("    TD-LTE通信（1:支持）:"+(value>>5&0x01));
        builder.append("\r\n");
        builder.append("    其他通讯方式（1:支持）:"+(value>>7&0x01));
        builder.append("\r\n");

        return builder.toString();
    }

    private String handle0104(JT808_2019Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("终端->平台:设置终端参数应答");
        builder.append("\r\n");
        builder.append("应答流水号:"+cmd.readInt(2));
        int size = cmd.readInt(1);
        builder.append("参数总数:"+size);

        handleA10(cmd,builder);

        return builder.toString();
    }

    private void handleA10(JT808_2019Cmd cmd, StringBuilder builder){
        do{
            int id = cmd.readInt(4);
            int len = cmd.readInt(1);
            builder.append("    "+Integer.toHexString(id)+"-");
            switch (id) {
                case 0x0001:
                    builder.append("终端心跳发送间隔，秒:" + cmd.readInt(len));
                    break;
                case 0x0002:
                    builder.append("TCP消息应答超时时间，秒:" + cmd.readInt(len));
                    break;
                case 0x0003:
                    builder.append("TCP消息重传次数:" + cmd.readInt(len));
                    break;
                case 0x0004:
                    builder.append("UDP消息应答超时时间，秒:" + cmd.readInt(len));
                    break;
                case 0x0005:
                    builder.append("UDP消息重传次数:" + cmd.readInt(len));
                    break;
                case 0x0006:
                    builder.append("SMS消息应答超时时间，秒:" + cmd.readInt(4));
                    break;
                case 0x0007:
                    builder.append("SMS消息重传次数:" + cmd.readInt(4));
                    break;
                case 0x0010:
                    builder.append("主服务器APN/PPP号码，无线通信拨号访问点:" + cmd.readString(len));
                    break;
                case 0x0011:
                    builder.append("主服务器无线通信拨号用户名:" + cmd.readString(len));
                    break;
                case 0x0012:
                    builder.append("主服务器无线通信拨号密码:" + cmd.readString(len));
                    break;
                case 0x0013:
                    builder.append("主服务器地址,IP或域名:" + cmd.readString(len));
                    break;
                case 0x0014:
                    builder.append("备份服务器APN，无线通信拨号访问点:" + cmd.readString(len));
                    break;
                case 0x0015:
                    builder.append("备份服务器无线通信拨号用户名:" + cmd.readString(len));
                    break;
                case 0x0016:
                    builder.append("备份服务器无线通信拨号密码:" + cmd.readString(len));
                    break;
                case 0x0017:
                    builder.append("备份服务器地址,IP或域名:" + cmd.readString(len));
                    break;
                case 0x001A:
                    builder.append("IC卡认证主服务器地址,IP或域名（保留）:" + cmd.readString(len));
                    break;
                case 0x001B:
                    builder.append("IC卡认证主服务器TCP端口（保留）:" + cmd.readInt(len));
                    break;
                case 0x001C:
                    builder.append("IC卡认证备份服务器地址IP或域名（保留）:" + cmd.readString(len));
                    break;
                case 0x001D:
                    builder.append("IC卡认证备份服务器TCP端口（保留）:" + cmd.readInt(len));
                    break;
                case 0x0020: {
                    HashMap<Integer, String> list = new HashMap<>();
                    int type = cmd.readInt(len);
                    list.put(0, "定时汇报");
                    list.put(1, "定距汇报");
                    list.put(2, "定时 + 定距汇报");
                    builder.append("位置汇报策略:" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0021: {
                    HashMap<Integer, String> list = new HashMap<>();
                    int type = cmd.readInt(len);
                    list.put(0, "根据ACC状态");
                    list.put(1, "根据登录状态 + ACC状态，先判断登录状态，若登录再根据ACC状态");
                    builder.append("位置汇报方案:" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0022:
                    builder.append("未登录汇报时间间隔，秒:" + cmd.readInt(len));
                    break;
                case 0x0023:
                    builder.append("从服务器APN:" + cmd.readString(len));
                    break;
                case 0x0024:
                    builder.append("从服务器拨号用户名:" + cmd.readString(len));
                    break;
                case 0x0025:
                    builder.append("从服务器拨号密码:" + cmd.readInt(len));
                    break;
                case 0x0026:
                    builder.append("从服务器备份IP或域名:" + cmd.readInt(len));
                    break;
                case 0x0027:
                    builder.append("休眠时汇报时间间隔，秒:" + cmd.readInt(len));
                    break;
                case 0x0028:
                    builder.append("紧急报警时汇报时间间隔，秒:" + cmd.readInt(len));
                    break;
                case 0x0029:
                    builder.append("缺省时间汇报距离间隔，米:" + cmd.readInt(len));
                    break;
                case 0x002C:
                    builder.append("缺省距离汇报间隔，米:" + cmd.readInt(len));
                    break;
                case 0x002D:
                    builder.append("驾驶员未登录汇报距离间隔，米:" + cmd.readInt(len));
                    break;
                case 0x002E:
                    builder.append("休眠时汇报距离间隔，米:" + cmd.readInt(len));
                    break;
                case 0x002F:
                    builder.append("紧急报警时汇报距离间隔，米:" + cmd.readInt(len));
                    break;
                case 0x0030:
                    builder.append("拐点补传角度:" + cmd.readInt(len));
                    break;
                case 0x0031:
                    builder.append("电子围栏半径（米）:" + cmd.readInt(len));
                    break;
                case 0x0032:
                    builder.append("违规行驶时段范围:" + cmd.readBCD(len));
                    break;
                case 0x0040:
                    builder.append("监控平台电话号码:" + cmd.readString(len));
                    break;
                case 0x0041:
                    builder.append("复位电话号码:" + cmd.readString(len));
                    break;
                case 0x0042:
                    builder.append("恢复出厂设置电话号码:" + cmd.readInt(len));
                    break;
                case 0x0043:
                    builder.append("监控指挥中心SMS电话号码:" + cmd.readInt(len));
                    break;
                case 0x0044:
                    builder.append("接收终端SMS文本报警号码:" + cmd.readInt(len));
                    break;
                case 0x0045: {
                    HashMap<Integer, String> list = new HashMap<>();
                    int type = cmd.readInt(len);
                    list.put(0, "自动接听");
                    list.put(1, "ACC ON时自动接听，OFF时手动接听");
                    builder.append("终端电话接听策略:" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0046:
                    builder.append("每次最长通话时间，秒:" + cmd.readInt(len));
                    break;
                case 0x0047:
                    builder.append("当月最长通话时间，秒:" + cmd.readInt(len));
                    break;
                case 0x0048:
                    builder.append("监听电话号码:" + cmd.readString(len));
                    break;
                case 0x0049:
                    builder.append("监管平台特权短信号码:" + cmd.readString(len));
                    break;
                case 0x0050:
                    builder.append("报警屏蔽字，与位置信息汇报消息中的报警标志相对应，相应位为1则相应报警被屏蔽:" + cmd.readBCD(len));
                    break;
                case 0x0051:
                    builder.append("报警发送文本SMS开关，与位置信息汇报消息中的报警标志相对应，相应位为1则相应报警时发送文本SMS:" + cmd.readBCD(len));
                    break;
                case 0x0052:
                    builder.append("报警拍摄开关，与位置信息汇报消息中的报警标志相对应，相应位为1则相应报警时摄像头拍摄:" + cmd.readBCD(len));
                    break;
                case 0x0053:
                    builder.append("报警拍摄存储标志，与位置信息汇报消息中的报警标志相对应，相应位为1则对相应报警时拍的照片进行存储，否则实时上传:" + cmd.readBCD(len));
                    break;
                case 0x0054:
                    builder.append("关键标志，与位置信息汇报消息中的报警标志相对应，相应位为1则对相应报警为关键报警:" + cmd.readBCD(len));
                    break;
                case 0x0055:
                    builder.append("最高速度，KM/H:" + cmd.readInt(len));
                    break;
                case 0x0056:
                    builder.append("超速持续时间，秒:" + cmd.readInt(len));
                    break;
                case 0x0057:
                    builder.append("连续驾驶时间门限，秒:" + cmd.readInt(len));
                    break;
                case 0x0058:
                    builder.append("当天累计驾驶时间门限，秒:" + cmd.readInt(len));
                    break;
                case 0x0059:
                    builder.append("最小休息时间，秒:" + cmd.readInt(len));
                    break;
                case 0x005A:
                    builder.append("最长停车时间，秒:" + cmd.readInt(len));
                    break;
                case 0x005B:
                    builder.append("超速预警差值，单位为1/10千米每小时:" + cmd.readInt(len));
                    break;
                case 0x005C:
                    builder.append("疲劳预警差值，单位为秒:" + cmd.readInt(len));
                    break;
                case 0x005D:
                    builder.append("碰撞报警参数:");
                    builder.append("    碰撞加速度（0.1g）:" + cmd.readInt(1));
                    builder.append("    碰撞时间（毫秒）:" + cmd.readInt(1));
                    if (len != 2) {
                        cmd.moveIndex(len - 2);
                    }
                    break;
                case 0x005E:
                    builder.append("侧翻报警参数设置，侧翻角度:" + cmd.readInt(len));
                    break;
                case 0x0064:{
                    int value = cmd.readInt(len);
                    builder.append("定时拍照控制:");
                    builder.append("\r\n");
                    builder.append("摄像头通道1定时拍照开关(0不允许,1允许):" + (value & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道2定时拍照开关(0不允许,1允许):" + (value >> 1 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道3定时拍照开关(0不允许,1允许):" + (value >> 2 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道4定时拍照开关(0不允许,1允许):" + (value >> 3 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道5定时拍照开关(0不允许,1允许):" + (value >> 4 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道1定时拍照存储(0存储,1上传):" + (value >> 8 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道2定时拍照开关(0存储,1上传):" + (value >> 9 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道3定时拍照开关(0存储,1上传):" + (value >> 10 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道4定时拍照开关(0存储,1上传):" + (value >> 11 & 0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道5定时拍照开关(0存储,1上传):" + (value >> 12 & 0x01));
                    builder.append("\r\n");

                    builder.append("定时时间单位（0.秒（小于5秒，按5秒处理）;1.分）:" + (value >> 16 & 0x01));
                    builder.append("\r\n");

                    builder.append("定时时间间隔:" + ((value >> 17) & 0xFFFF));
                    builder.append("\r\n");
                    break;
                }
                case 0x0065:{
                    int value = cmd.readInt(len);
                    builder.append("定距拍照控制:");
                    builder.append("\r\n");
                    builder.append("摄像头通道1定距拍照开关(0不允许,1允许):"+(value&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道2定距拍照开关(0不允许,1允许):"+(value>>1&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道3定距拍照开关(0不允许,1允许):"+(value>>2&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道4定距拍照开关(0不允许,1允许):"+(value>>3&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道5定距拍照开关(0不允许,1允许):"+(value>>4&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道1定距拍照存储(0存储,1上传):"+(value>>8&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道2定距拍照开关(0存储,1上传):"+(value>>9&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道3定距拍照开关(0存储,1上传):"+(value>>10&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道4定距拍照开关(0存储,1上传):"+(value>>11&0x01));
                    builder.append("\r\n");
                    builder.append("摄像头通道5定距拍照开关(0存储,1上传):"+(value>>12&0x01));
                    builder.append("\r\n");

                    builder.append("定距时间单位（0.米（小于100m，按100m处理）;1.千米）:"+(value>>16&0x01));
                    builder.append("\r\n");

                    builder.append("定距时间间隔:"+((value>>17)&0xFFFF));
                    builder.append("\r\n");
                    break;
                }
                case 0x0070:
                    builder.append("图像/视频质量，1～10，1最好:"+cmd.readInt(len));
                    break;
                case 0x0071:
                    builder.append("亮度:"+cmd.readInt(len));
                    break;
                case 0x0072:
                    builder.append("对比度:"+cmd.readInt(len));
                    break;
                case 0x0073:
                    builder.append("饱和度:"+cmd.readInt(len));
                    break;
                case 0x0074:
                    builder.append("色度:"+cmd.readInt(len));
                    break;
                case 0x0080:
                    builder.append("车辆里程表读数，1/10KM:"+cmd.readInt(len));
                    break;
                case 0x0081:
                    builder.append("车辆所在的省域ID，1～255（省级行政区划代码前2位；终端根据此ID生成所在省的简称即对应车牌号第一个汉字）:"+cmd.readInt(len));
                    break;
                case 0x0082:
                    builder.append("车辆所在的市域ID，1～255（行政区划代码的第3、4位）:"+cmd.readInt(len));
                    break;
                case 0x0083:
                    builder.append("公安交通管理部分颁发的机动车牌:"+cmd.readString(len));
                    break;
                case 0x0084:
                    builder.append("车牌颜色:"+cmd.readInt(len));
                    break;
                case 0x0090:
                    builder.append("GNSS定位模式:");
                    int value = cmd.readInt(len);
                    builder.append("    GPS定位（0:禁用,1:启用）:"+(value&0x01));
                    builder.append("\r\n");
                    builder.append("    北斗定位（0:禁用,1:启用）:"+(value>>1&0x01));
                    builder.append("\r\n");
                    builder.append("    GLONASS（0:禁用,1:启用）:"+(value>>2&0x01));
                    builder.append("\r\n");
                    builder.append("    Galileo（0:禁用,1:启用）:"+(value>>3&0x01));
                    break;
                case 0x0091: {
                    int type = cmd.readInt(len);
                    HashMap<Integer, String> list = new HashMap<>();
                    list.put(0, "4800");
                    list.put(1, "9600");
                    list.put(2, "19200");
                    list.put(3, "38400");
                    list.put(4, "57600");
                    list.put(5, "115200");

                    builder.append("GNSS波特率(" + type + ":" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0092:{
                    int type = cmd.readInt(len);
                    HashMap<Integer, String> list = new HashMap<>();
                    list.put(0, "500ms");
                    list.put(1, "1000ms");
                    list.put(2, "2000ms");
                    list.put(3, "3000ms");
                    list.put(4, "4000ms");

                    builder.append("GNSS波特率(" + type + ":" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0093:
                    builder.append("GNSS模块详细定位数据采集频率:"+cmd.readInt(len));
                    break;
                case 0x0094:{
                    int type = cmd.readInt(len);
                    HashMap<Integer, String> list = new HashMap<>();
                    list.put(0x00, "本地存储，不上传");
                    list.put(0x01, "按时间间隔上传");
                    list.put(0x02, "按距离间隔上传");
                    list.put(0x0B, "按累计时间上传，达到传输时间后自动停止上传");
                    list.put(0x0C, "按累计距离上传，达到距离后自动停止上传");
                    list.put(0x0D, "按累计条数上传，达到上传条数后自动停止上传");

                    builder.append("GNSS定位数据上传方式(" + type + ":" + list.getOrDefault(type, "未定义"));
                    break;
                }
                case 0x0095:
                    builder.append("GNSS定位数据上传设置（根据0x0094决定该值的单位：秒/米/条）:"+cmd.readInt(len));
                    break;
                case 0x0100:
                    builder.append("CAN总线通道1采集时间间隔，单位为毫秒，0为不采集:"+cmd.readInt(len));
                    break;
                case 0x0101:
                    builder.append("CAN总线通道1上传时间间隔，单位为秒，0为不上传:"+cmd.readInt(len));
                    break;
                case 0x0102:
                    builder.append("CAN总线通道2采集时间间隔，单位为毫秒，0为不采集:"+cmd.readInt(len));
                    break;
                case 0x0103:
                    builder.append("CAN总线通道2上传时间间隔，单位为秒，0为不上传:"+cmd.readInt(len));
                    break;
                case 0x0110:
                    builder.append("CAN总线ID单独采集设置:"+cmd.readBCD(len));
                    break;
                default:
                    builder.append("未定义ID("+id+"):"+cmd.readBCD(len));
                    break;
            }

            builder.append("\r\n");
        }while (cmd.leftSize() > 3);
    }

    private String handle0102(JT808_2019Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("终端->平台:终端鉴权");
        builder.append("\r\n");

        builder.append("鉴权码："+cmd.readString(cmd.readInt(1)));
        builder.append("\r\n");
        builder.append("IMEI："+cmd.readString(15));
        builder.append("\r\n");
        builder.append("软件版本："+cmd.readString(20));
        builder.append("\r\n");

        return builder.toString();
    }
}
